package cz.czu.pef.DataModelling.entityObjects;

import java.util.*;

import javax.persistence.*;

import org.hibernate.annotations.Index;

/**
 * PersonEntityImpl entity. This entity represents PersonEntityImpl with undertaken trainings and medicalExaminations.
 * 
 * @author rstribrn
 *
 */
@Entity
@Table(name="PERSON")
@NamedQueries({
	@NamedQuery(name="findPersonByName", query="SELECT p FROM PersonEntityImpl p WHERE p.firstName = :firstName AND p.lastName = :lastName")
})
public class PersonEntityImpl extends IdPersistenceEntityObjectImpl implements IdPersistenceEntityObject
{
	private static final long serialVersionUID = -3846628860514746169L;

	/*
	 * Entity attributes
	 */
	@Column(name="FIRST_NAME", nullable=false, length=200)
	@Index(name="IDX_PERSON_FN")
	private String firstName;

	@Column(name="LAST_NAME", nullable=false, length=200)
	@Index(name="IDX_PERSON_LN")
	private String lastName;

	@Column(name="BIRTH_DATE", nullable=true)
	@Index(name="IDX_PERSON_BIRTHDATE")
	private Date birthDate;

	@ManyToOne(fetch=FetchType.EAGER, optional=true, targetEntity=AddressEntityImpl.class) // no cascade
	private AddressEntityImpl address;

	/*
	 * Relations
	 */
	@ManyToMany(fetch = FetchType.EAGER, targetEntity = MedicalExaminationEntityImpl.class, cascade={CascadeType.REMOVE})
	@JoinTable(name="PERSON_MEDICAL_EXAMINATIONS")
	private Set<MedicalExaminationEntityImpl> medicalExaminations;

	@ManyToMany(fetch = FetchType.EAGER, targetEntity = TrainingEntityImpl.class, cascade={CascadeType.REMOVE})
	@JoinTable(name="PERSON_TRAININGS")
	private Set<TrainingEntityImpl> trainings;

	@OneToMany(fetch=FetchType.EAGER, targetEntity=MachineryEntityImpl.class, mappedBy="personOwner") // no cascade
	private Set<MachineryEntityImpl> machineries;

	@OneToMany(fetch=FetchType.EAGER, targetEntity=EmployeeEntityImpl.class, mappedBy="person", cascade={CascadeType.REMOVE})
	private Set<EmployeeEntityImpl> employees;

	public PersonEntityImpl()
	{
		super();
	}

	public PersonEntityImpl(final String fn, final String ln)
	{
		super();
		setFirstName(fn);
		setLastName(ln);
	}

	public PersonEntityImpl(final String fn, final String ln, AddressEntityImpl address)
	{
		setFirstName(fn);
		setLastName(ln);
		setAddress(address);
	}

	public AddressEntityImpl getAddress()
	{
		return address;
	}

	public String getFirstName()
	{
		return firstName;
	}

	public String getLastName()
	{
		return lastName;
	}

	public void setAddress(AddressEntityImpl address)
	{
		this.address = address;
	}

	public void setFirstName(final String firstName)
	{
		this.firstName = firstName;
	}

	public void setLastName(final String lastName)
	{
		this.lastName = lastName;
	}

	public Date getBirthDate()
	{
		return birthDate;
	}

	public void setBirthDate(Date birthDate)
	{
		this.birthDate = birthDate;
	}

	public Set<EmployeeEntityImpl> getEmployees()
	{
		return employees;
	}

	public List<EmployeeEntityImpl> getEmployeesAsList()
	{
		return new ArrayList<EmployeeEntityImpl>(getEmployees());
	}

	public void setEmployees(Set<EmployeeEntityImpl> employees)
	{
		this.employees = employees;
	}

	public Set<MachineryEntityImpl> getMachineries()
	{
		return machineries;
	}

	public List<MachineryEntityImpl> getMachineriesAsList()
	{
		return new ArrayList<MachineryEntityImpl>(getMachineries());
	}

	public Set<MedicalExaminationEntityImpl> getMedicalExaminations()
	{
		return medicalExaminations;
	}

	public List<MedicalExaminationEntityImpl> getMedicalExaminationsAsList()
	{
		return new ArrayList<MedicalExaminationEntityImpl>(getMedicalExaminations());
	}

	public void addMedicalExamination(MedicalExaminationEntityImpl medicalExamination)
	{
		if (medicalExaminations == null)
			medicalExaminations = new HashSet<MedicalExaminationEntityImpl>();
		medicalExaminations.add(medicalExamination);
	}

	public Set<TrainingEntityImpl> getTrainings()
	{
		return trainings;
	}

	public List<TrainingEntityImpl> getTrainingsAsList()
	{
		return new ArrayList<TrainingEntityImpl>(getTrainings());
	}

	public void addTraining(TrainingEntityImpl training)
	{
		if (trainings == null)
			trainings = new HashSet<TrainingEntityImpl>();

		trainings.add(training);
	}

	/* (non-Javadoc)
	 * @see cz.czu.pef.DataModelling.domainObjects.Person#canBeRemoved()
	 */
	@Override
	public boolean canBeRemoved()
	{
		return (getMachineries().size() == 0) && getEmployees().size() == 0;
	}

    
  public void setMedicalExaminations(Set<MedicalExaminationEntityImpl> medicalExaminations)
  {
    this.medicalExaminations = medicalExaminations;
  }

  
  public void setTrainings(Set<TrainingEntityImpl> trainings)
  {
    this.trainings = trainings;
  }

  
  public void setMachineries(Set<MachineryEntityImpl> machineries)
  {
    this.machineries = machineries;
  }

    @Override
	public String toString()
	{
		StringBuilder builder = new StringBuilder();
		builder.append("PersonEntityImpl [getFirstName()=");
		builder.append(getFirstName());
		builder.append(", getLastName()=");
		builder.append(getLastName());
		builder.append(", getBirthDate()=");
		builder.append(getBirthDate());
		builder.append(", getAddress()=");
		builder.append(getAddress());
		builder.append(", getMedicalExaminations()=");
		builder.append(getMedicalExaminations());
		builder.append(", getTrainings()=");
		builder.append(getTrainings());
		builder.append("]");
		return builder.toString();
	}

}